import type { OperationPerformance } from './types'
import { getBADAModel } from './core'
import { ft2m, kt2Mps, mps2Kt } from '@/widgets'
import { airDataByFL, flightLevels } from './flight-envelope'

export interface ThrustItem {
  alt: number
  value: number
  TAS: number
}

export interface ThrustAltProfile {
  CAS: number
  mass: number
  maxClimb: ThrustItem[]
  maxCruise: ThrustItem[]
  descent: ThrustItem[]
  drag: ThrustItem[]
}

const cVMin = 1.3
const cThCr = 0.95
const ftMaxAp = 8000.0
const ftMaxLd = 3000.0
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const hMaxAp = ft2m(ftMaxAp)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const hMaxLd = ft2m(ftMaxLd)

export function calcThrustAltProfileById(id: string, KCAS: number): ThrustAltProfile {
  const model = getBADAModel(id)!
  return calcThrustAltProfile(model.performance, KCAS)
}

function calcThrustAltProfile(op: OperationPerformance, KCAS: number): ThrustAltProfile {
  if (op.engineType === 'Jet') {
    return doCalcThrustAltProfile(op, KCAS, calcJetMaxClimbThrust)
  }
  if (op.engineType === 'Turboprop') {
    return doCalcThrustAltProfile(op, KCAS, calcTurbopropMaxClimbThrust)
  }
  return doCalcThrustAltProfile(op, KCAS, calcPistonMaxClimbThrust)
}

function doCalcThrustAltProfile(
  op: OperationPerformance,
  KCAS: number,
  fn: (KTAS: number, altFt: number, op: OperationPerformance) => number
): ThrustAltProfile {
  const flMax = op.hMax / 100.0
  let idx = 0

  const G0 = 9.80665
  const maxClimb: ThrustItem[] = []
  const maxCruise: ThrustItem[] = []
  const descent: ThrustItem[] = []
  const drag: ThrustItem[] = []
  const CAS = kt2Mps(KCAS)
  const mass = op.massRef
  const S = op.S
  const cD0 = op.cDrag0CR
  const cD2 = op.cDrag2CR
  for (const fl of flightLevels) {
    if (fl > flMax) {
      break
    }
    const altFt = fl * 100.0
    const alt = ft2m(altFt)
    const ad = airDataByFL[idx++]
    const TAS = ad.CAS2TAS(CAS)
    const KTAS = mps2Kt(TAS)
    const thrust = fn(KTAS, altFt, op)
    maxClimb.push({ alt, value: thrust, TAS })
    maxCruise.push({ alt, TAS, value: thrust * cThCr })
    descent.push({ alt, TAS, value: calcDescentThrust(thrust, altFt, KCAS, op) })

    const t2 = TAS * TAS
    const cL = (2 * mass * 1000.0 * G0) / ad.density / S / t2
    const cD = cD0 + cD2 * cL * cL
    const d = (cD * ad.density * t2 * S) / 2.0
    drag.push({ value: d, alt, TAS })
  }
  return { maxClimb, maxCruise, descent, CAS, drag, mass }
}

export function calcMaxClimbThrust(KTAS: number, altFl: number, op: OperationPerformance): number {
  if (op.engineType === 'Jet') {
    return calcJetMaxClimbThrust(KTAS, altFl, op)
  }
  if (op.engineType === 'Turboprop') {
    return calcTurbopropMaxClimbThrust(KTAS, altFl, op)
  }
  return calcPistonMaxClimbThrust(KTAS, altFl, op)
}

function calcTurbopropMaxClimbThrust(
  KTAS: number,
  altFt: number,
  op: OperationPerformance
): number {
  return (op.cThrCmb1 / KTAS) * (1 - altFt / op.cThrCmb2) + op.cThrCmb3
}
function calcPistonMaxClimbThrust(KTAS: number, altFt: number, op: OperationPerformance): number {
  return op.cThrCmb1 * (1 - altFt / op.cThrCmb2) + op.cThrCmb3 / KTAS
}

function calcJetMaxClimbThrust(KTAS: number, altFt: number, op: OperationPerformance): number {
  return op.cThrCmb1 * (1 - altFt / op.cThrCmb2 + op.cThrCmb3 * altFt * altFt)
}

export function calcDescentThrust(
  cmbThrust: number,
  altFt: number,
  KCAS: number,
  op: OperationPerformance
): number {
  if (altFt >= op.hPDes) {
    return cmbThrust * op.cThrDesHigh
  }
  if (altFt >= ftMaxAp) {
    return cmbThrust * op.cThrDesLow
  }
  if (KCAS >= op.vStallCR * cVMin) {
    return cmbThrust * op.cThrDesLow
  }
  if (altFt >= ftMaxLd) {
    return cmbThrust * op.cThrDesAP
  }
  if (KCAS >= op.vStallAP * cVMin) {
    return cmbThrust * op.cThrDesAP
  }
  return cmbThrust * op.cThrDesLD
}

// function calcJetThrustAltProfile (op: OperationPerformance, KCAS: number): ThrustAltProfile {
//   const flMax = op.hMax / 100.0
//   let idx = 0
//   const maxClimb: ThrustItem [] = []
//   const maxCruise: ThrustItem[] = []
//   const descent: ThrustItem[] = []
//   const CAS = kt2Mps(KCAS)
//   for (const fl of flightLevels) {
//     if (fl > flMax) {
//       break
//     }
//     const altFt = fl * 100.0
//     const alt = ft2m(altFt)
//     const ad = airDataByFL[idx++]
//     const TAS = ad.CAS2TAS(CAS)
//     const thrust = op.cThrCmb1 * (1 - altFt / op.cThrCmb2 + op.cThrCmb3 * altFt * altFt)
//     maxClimb.push({ alt, thrust, TAS })
//     maxCruise.push({ alt, TAS, thrust: thrust * cThCr })
//     descent.push({ alt, TAS, thrust: calcDescentThrust(thrust, altFt, KCAS, op) })
//   }
//   return { maxClimb, maxCruise, descent, CAS }
// }
